package gui;
import dataset.DataPoint;
import dataset.DataSet;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.geom.Point2D;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JComponent;
import javax.swing.Timer;

/**
 * Creates an component that is a viewer onto an animation.
 * 
 * @author Robert C. Duvall edited by rwb10 & sab60
 */
@SuppressWarnings("serial")
public abstract class Axis extends JComponent {
    private static final int BORDER_WIDTH = 50;

    // drives simulation
    private Timer myTimer;
    // input state
    private int myLastKeyPressed;
    private Point myLastMousePosition;
    private DataSet myDataSet;
    private Dimension myGraphSize;
    private String myTitle;

    /**
     * Initializes the canvas.
     * 
     * @param size Size of the canvas.
     */
    public Axis (Dimension size) {
        // request component size
        myGraphSize = size;
        setMyTitle("ScatterPlot of ??");
        setPreferredSize(size);
        // set component to receive user input
        setFocusable(true);
        requestFocus();
    }

    /**
     * Add a DataSet.
     * @param setToAdd DataSet to add.
     */
    public void loadDataSet (DataSet setToAdd) {
        myDataSet = setToAdd;
        setMyTitle(myDataSet.getTitle());
    }
    /**
     * Starts the applet's action, i.e., starts the animation.
     */
    public void start () {
        myTimer.start();
    }

    /**
     * Take one step in the animation.
     * 
     * @param elapsedTime Time since last call.
     */
    public void step (double elapsedTime) {
        // indirectly causes paint to be called
        repaint();
    }

    /**
     * Stops the applet's action, i.e., the animation.
     */
    public void stop () {
        myTimer.stop();
    }

    /**
     * Returns the last key pressed by the player (or -1 if none pressed).
     * 
     * @see java.awt.event.KeyEvent
     */
    public int getLastKeyPressed () {
        return myLastKeyPressed;
    }

    /**
     * Returns the last position of the mouse in the canvas.
     */
    public Point getLastMousePosition () {
        return myLastMousePosition;
    }

    /**
     * Paint the contents of the canvas.
     * 
     * Never called by you directly, instead called by Java runtime
     * when area of screen covered by this container needs to be
     * displayed (i.e., creation, uncovering, change in status)
     * 
     * @param pen used to paint shape on the screen
     */
    @Override
    public void paintComponent (Graphics pen) {
        paintAxis(pen);
        if (myDataSet != null) {
            paintData(pen);
        }
        paintTicMarks(pen);
    }

    abstract void paintTicMarks (Graphics pen);
    abstract void paintData(Graphics pen);

    /**
     * 
     * @return
     */
    public List<Point2D> normalizeData () {
        double minXVal = myDataSet.getMinX();
        double maxXVal = myDataSet.getMaxX();
        double minYVal = myDataSet.getMinY();
        double maxYVal = myDataSet.getMaxY();
        double xDataRange = maxXVal - minXVal;
        double yDataRange = maxYVal - minYVal;
        double xNormalizer = xDataRange / getGraphSize().width;
        double yNormalizer = yDataRange / getGraphSize().height;
        List<Point2D> normalizedData = new ArrayList<Point2D>();
        for (DataPoint data : myDataSet.getData()) {
            int xNorm = (int) (data.getX() / xNormalizer);
            int yNorm = (int) (data.getY() / yNormalizer);
            Point dataPoint = new Point(xNorm, yNorm);
            normalizedData.add(dataPoint);
        }
        return normalizedData;
    }



    /**
     * Paint a line.
     * @param pen       Graphics to paint with.
     * @param p1        Start point of line.
     * @param p2        End point of line.
     * @param color     Color of line.
     */
    public static void paintLine (Graphics pen, Point2D p1, Point2D p2, Color color) {
        pen.setColor(color);
        pen.drawLine((int) p1.getX(), (int) p1.getY(),
                (int) p2.getX(), (int) p2.getY());
    }
    /**
     * Paint the outer lines of the axis and the title.
     * @param pen Pen to draw axis.
     */
    public void paintAxis (Graphics pen) {
        pen.setColor(Color.WHITE);
        pen.fillRect(0, 0, getSize().width, getSize().height);
        pen.setColor(Color.BLACK);
        pen.drawLine(BORDER_WIDTH, BORDER_WIDTH, BORDER_WIDTH, myGraphSize.height - BORDER_WIDTH);
        pen.drawLine(BORDER_WIDTH, myGraphSize.height - BORDER_WIDTH, myGraphSize.width - 
                BORDER_WIDTH, myGraphSize.height - BORDER_WIDTH);
    }
    /**
     * Paint a circle.
     * @param pen       Graphics to paint with.
     * @param p         Point to draw center at.
     * @param radius    Radius of circle to draw.
     * @param color     Color of circle to draw.
     */
    public static void paintCircle (Graphics2D pen, Point2D p, int radius, Color color) {
        pen.setColor(color);
        pen.fillOval((int) p.getX() - radius / 2, (int) p.getY() - radius / 2,
                radius, radius);
    }

    /**
     * 
     * @return Dimension of graph.
     */
    public Dimension getGraphSize() {
        Dimension plotSize = new Dimension((int) myGraphSize.getWidth() - 2 * BORDER_WIDTH,
                (int) myGraphSize.getHeight() - 2 * BORDER_WIDTH);
        return plotSize;
    }

    /**
     * @return the myTitle
     */
    public String getMyTitle () {
        return myTitle;
    }

    /**
     * @param myFileTitle the myTitle to set
     */
    public void setMyTitle (String myFileTitle) {
        this.myTitle = myFileTitle;
    }

}
